var util = require('util');
var bleno = require('bleno');

var BlenoPrimaryService = bleno.PrimaryService;
var BlenoCharacteristic = bleno.Characteristic;
var BlenoDescriptor = bleno.Descriptor;

console.log('bleno');

var readlocalhost = function() {
    var mac = new Buffer(6);
    for (var i=0; i<6; i++) {
        var hex = parseInt(bleno.address[3*i], 16);
        hex = (hex << 4) + parseInt(bleno.address[3*i+1], 16);
        mac[i] = hex;
    }
    return mac;
};

var localeMACAddr = new Buffer(6);

var teststep = 0;
var targetstep = 10000;

var ReadMACAddressCharacteristic = function() {
  ReadMACAddressCharacteristic.super_.call(this, {
    uuid: 'fec9',
    properties: ['read']
  });
};
util.inherits(ReadMACAddressCharacteristic, BlenoCharacteristic);

ReadMACAddressCharacteristic.prototype.onReadRequest = function(offset, callback) {
  console.log('ReadMACAddressCharacteristic Read');
  var result = this.RESULT_SUCCESS;
  callback(result, localeMACAddr);
};

var CurrentPedometerMeasChar = function() {
  CurrentPedometerMeasChar.super_.call(this, {
    uuid: 'fea1',
    properties: ['read', 'notify']
  });
};

util.inherits(CurrentPedometerMeasChar, BlenoCharacteristic);

CurrentPedometerMeasChar.prototype.onReadRequest = function(offset, callback) {
  console.log('CurrentPedometerMeasChar Read');
  var result = this.RESULT_SUCCESS;
  var data = new Buffer(4);
  data[0] = 0x01;
  data[1] = this.counter & 0xff;
  data[2] = (this.counter & 0xff00) >> 8;
  data[3] = (this.counter & 0xff0000) >> 16;
  callback(result, data);
};


CurrentPedometerMeasChar.prototype.onSubscribe = function(maxValueSize, updateValueCallback) {
  console.log('CurrentPedometerMeasChar subscribe');

  this.counter = 0;
  this.changeInterval = setInterval(function() {
    var data = new Buffer(4);
    data[0] = 0x01;
    data[1] = this.counter & 0xff;
    data[2] = (this.counter & 0xff00) >> 8;
    data[3] = (this.counter & 0xff0000) >> 16;

    console.log('CurrentPedometerMeasChar update value: ' + this.counter + ' ' + data.toString('hex'));
    updateValueCallback(data);
    this.counter++;
    teststep = this.counter;
    if (teststep > 30) {
      clearInterval(this.changeInterval);
      this.changeInterval = null;
    }
  }.bind(this), 1000);
};

CurrentPedometerMeasChar.prototype.onUnsubscribe = function() {
  console.log('CurrentPedometerMeasChar unsubscribe');

  if (this.changeInterval) {
    clearInterval(this.changeInterval);
    this.changeInterval = null;
  }
};

CurrentPedometerMeasChar.prototype.onNotify = function() {
  console.log('CurrentPedometerMeasChar on notify');
};

var TargetPedometerCharcteristic = function() {
  TargetPedometerCharcteristic.super_.call(this, {
    uuid: 'fea2',
    properties: ['read', 'write', 'indicate']
  });
};

util.inherits(TargetPedometerCharcteristic , BlenoCharacteristic);

TargetPedometerCharcteristic.prototype.onReadRequest = function(offset, callback) {
  console.log('TargetPedometerCharcteristic Read');
  var result = this.RESULT_SUCCESS;
  var data = new Buffer(4);
  data[0] = 0x01;
  data[1] = targetstep & 0xff;
  data[2] = (targetstep & 0xff00) >> 8;
  data[3] = (targetstep & 0xff0000) >> 16;
  callback(result, data);
};

TargetPedometerCharcteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) {
  console.log('TargetPedometerCharcteristic write request: ' + data.toString('hex') + ' ' + offset + ' ' + withoutResponse);
  targetstep = data;

  callback(this.RESULT_SUCCESS);
};

TargetPedometerCharcteristic.prototype.onSubscribe = function(maxValueSize, updateValueCallback) {
  console.log('TargetPedometerCharcteristic subscribe');
  setTimeout(function() {
    var data = new Buffer(4);
    targetstep += 100;
    data[0] = 0x01;
    data[1] = targetstep & 0xff;
    data[2] = (targetstep & 0xff00) >> 8;
    data[3] = (targetstep & 0xff0000) >> 16;
    console.log('TargetPedometerCharcteristic update value: ' + targetstep);
    updateValueCallback(data);
  }.bind(this), 5000);
};

TargetPedometerCharcteristic.prototype.onUnsubscribe = function() {
  console.log('TargetPedometerCharcteristic unsubscribe');
};

TargetPedometerCharcteristic.prototype.onIndicate = function() {
  console.log('TargetPedometerCharcteristic on indicate');
};

function SampleService() {
  SampleService.super_.call(this, {
    uuid: 'fee7',
    characteristics: [
      // new DynamicReadOnlyCharacteristic(),
      // new LongDynamicReadOnlyCharacteristic(),
      new CurrentPedometerMeasChar(),
      new TargetPedometerCharcteristic(),
      new ReadMACAddressCharacteristic(),
      // new WriteOnlyCharacteristic(),
      // new NotifyOnlyCharacteristic(),
      // new IndicateOnlyCharacteristic()
    ]
  });
}

util.inherits(SampleService, BlenoPrimaryService);

bleno.on('stateChange', function(state) {
  console.log('on -> stateChange: ' + state + ', address = ' + bleno.address);

  if (state === 'poweredOn') {
    var advData = new Buffer([0x02, 0x01, 0x06, 0x03, 0x03, 0xE7, 0xFE,
		0x07, 0x09, 0x47, 0x75, 0x6D, 0x70, 0x4A, 0x42, // GumpJB
        0x09, 0xFF, 0x33, 0x02,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
    localeMACAddr = readlocalhost();	
    for (var i=0; i<6; i++) {
        advData[19+i] = localeMACAddr[i];
    }
    bleno.startAdvertisingWithEIRData(advData);
  } else {
    bleno.stopAdvertising();
  }
});

// Linux only events /////////////////
bleno.on('accept', function(clientAddress) {
  console.log('on -> accept, client: ' + clientAddress);

  bleno.updateRssi();
});

bleno.on('disconnect', function(clientAddress) {
  console.log('on -> disconnect, client: ' + clientAddress);
});

bleno.on('rssiUpdate', function(rssi) {
  console.log('on -> rssiUpdate: ' + rssi);
});
//////////////////////////////////////

bleno.on('mtuChange', function(mtu) {
  console.log('on -> mtuChange: ' + mtu);
});

bleno.on('advertisingStart', function(error) {
  console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));

  if (!error) {
    bleno.setServices([
      new SampleService()
    ]);
  }
});

bleno.on('advertisingStop', function() {
  console.log('on -> advertisingStop');
});

bleno.on('servicesSet', function(error) {
  console.log('on -> servicesSet: ' + (error ? 'error ' + error : 'success'));
});
